<template>
  <ul>
    <li
      v-for='(item, index) of nodeData'
      v-show="!item.hasOwnProperty('visible') || item.visible"
      :key="item.key"
      :class="{onLyLi:item.parentId === null && treeData.length===1}">
      <div
        class="item-handle-area"
        :class="{'node-selected':item.checked}"
        @click="handleNode(item)"
        @mouseenter="treeMouseEnter(item)"
        @mouseleave="treeMouseLeave(item)">
        <i v-if="isLeaf(item)"
           @click.stop='handleNodeExpand(item, index)'
           class="iconfont defaultTreeColor"
           :class="[ item.open ? options.iconClass.open : options.iconClass.close ]">
        </i>

        <i v-else
           class="iconfont defaultTreeColor"
           :class="leafIcon(item)">
        </i>

        <span
          class="halo-tree-icon_loading halo-tree-iconEle defaultTreeColor"
          v-show="item.loading">
              </span>

        <span class="label" :class="{notAllowed: item.notAllowed}" :title="item[options.labelKey]">{{ item[options.labelKey] }}</span>

        <div
          class="dapart-arror"
          :class="{'dapart-arror-icon': !item.textArr}"
          v-if="item.showArr && item.openArr"
          @click.stop="departHandle(item)">
          <p v-if="item.textArr">{{item.textArr}}</p>
          <i v-else class="iconfont icon-jiantou"></i>
        </div>

        <div class="inputCheck"
             :class="{notAllNodes: item.nodeSelectNotAll, inputHover: item.checked}"
             :style="{width:inputWidth+'px', height:inputWidth+'px'}"
             v-show="options.showCheckbox && !item.closeCheck"
             @click.stop="checkBoxChange(item)">
          <i class="iconfont icon-tick" v-if="item.nodeSelectNotAll" style="color: #fff;"></i>
          <i
            class="iconfont icon-tick"
            :class="{'checked': item.checked}"
            v-if="options.showCheckbox && !item.nodeSelectNotAll  && item.checked"
            :checked="item.checked"
            :key="item.key"
          ></i>
        </div>

        <zz-select
          class="depart-select"
          v-if="item.showSelect && item.select"
          type="select"
          :border= false
          width = "auth"
          :options="{width: '40px'}"
          :option="item.select"
          :data="item"
          name = "操作"
          @optionClick="treeSelectCallback"></zz-select>
      </div>
      <tree-node
        ref="treenode"
        v-show='item.open'
        v-if="item.children && item.children.length > 0"
        @handlecheckedChange="handlecheckedChange"
        :options="options"
        :tree-data="item.children">
      </tree-node>
    </li>
  </ul>
</template>
<script>
  import { mapGetters } from 'vuex'
  export default {
    name: 'treeNode',
    props: {
      treeData: Array,
      options: Object,
      isLazy: {
        type: Boolean,
        default: false
      }
    },
    data () {
      return {
        nodeData: [],
        isMoveDepart: false
      }
    },
    created () {
      const parent = this.$parent
      if (parent.isTree) {
        this.tree = parent
      } else {
        this.tree = parent.tree
      }
      const tree = this.tree
      if (!tree) {
        console.warn('找不到树节点')
      }
      this.nodeData = (this.treeData || []).slice(0)
    },
    computed: {
      ...mapGetters({
        last: 'getLastTree'
      }),
      inputWidth () {
        if (this.checkFirfox()) {
          return 18
        }
        return 17
      }
    },
    watch: {
      treeData (data) {
        for (let item of data) {
          if (item.checked) {
            this.$store.commit('muLastTree', item)
            break
          }
        }
        this.nodeData = (data || []).slice(0)
      }
    },
    methods: {
      checkFirfox () {
        let u = navigator.userAgent
        if (u.indexOf('Gecko') > -1 && u.indexOf('KHTML') === -1) {
          return true
        }
        return false
      },
      checkBoxChange (node) {
        // 选择框
        if (this.options.multiple) {
          this.$set(node, 'checked', !node.checked)
        } else {
          this.handleNode(node)
        }
        this.handlecheckedChange(node)
      },
      handlecheckedChange (node) {
        this.$emit('handlecheckedChange', node)
      },
      handleNodeExpand (node, index) {
        if (node.open) {
          this.$set(node, 'open', false)
          return
        }
        if (node.hasOwnProperty('children') && node.children.length > 0 && !this.isLazy) {
          this.$set(node, 'open', true)
          return
        }
        if (!node.open && this.options.lazy && this.options.load) {
          try {
            this.$set(node, 'loading', true)
            this.options.load(node, index).then(() => {
              this.$set(node, 'open', true)
              this.$set(node, 'loaded', true)
              this.$set(node, 'loading', false)
              if (this.options.showCheckbox) {
                this.handlecheckedChange(node)
              }
            })
          } catch (e) {
            console.log('Get Child Error')
          }
        }
      },
      handleNode (node) {
        if (node.notAllowed) {
          return
        }
        if (this.options.showCheckbox) {
          this.tree.$emit('node-click-check', node)
          return
        }
        this.nodeData.forEach(x => {
          x.checked = false
        })
        if (this.last) {
          if (this.last.key !== node.key) {
            this.$set(node, 'checked', !node.checked)
            this.$store.commit('muLastTreeChecked', false)
            this.$store.commit('muLastTree', node)
          }
        } else {
          this.$store.commit('muLastTree', node)
          this.$set(node, 'checked', true)
        }
        this.$set(node, 'checked', true)
        this.tree.$emit('node-click', node)
      },
      async handleClickAddNode (item, index) {
        try {
          return Promise.resolve(true)
        } catch (e) {
          return Promise.reject(e)
        }
      },
      treeSelectCallback (data) {
        this.tree.$emit('node-select', data)
      },
      treeMouseEnter (item) {
        item.showArr = true
        item.showSelect = true
      },
      treeMouseLeave (item) {
        item.showArr = false
        item.showSelect = false
      },
      /**
       * 叶子节点的 icon
       * @param item
       */
      leafIcon (node) {
        return this.options.leafIcon(node)
      },
      isLeaf (item) {
        if (item.hasOwnProperty('closeLeaf')) {
          return false
        }
        if (item.hasOwnProperty('leaf') && item.leaf) {
          return false
        }
        return item.children && item.children.length > 0 || this.options.hasOwnProperty('lazy') && this.options.lazy && !item.hasOwnProperty('loaded')
      },
      // 点击悬浮箭头
      departHandle (item) {
        this.tree.$emit('node-arrow', item)
      }
    }
  }
</script>
<style lang="scss"  scoped>
  .halo-tree {
    font-size: 14px;
    min-height: 20px;
    border-radius: 4px;
    ul, li{
      margin: 0;
      padding: 0;
    }
    .node-selected {
      color: $color;
    }
    .notAllowed{
      cursor: not-allowed;
    }
    li {
      line-height: 20px;
      margin: 0;
      padding: 4px 0 4px 16px;
      position: relative;
      list-style: none;
      user-select: none;
      &:hover{
        cursor: pointer;
      }
      span{
        display: inline-block;
        padding: 3px 0;
        text-decoration: none;
        border-radius: 3px;
        width: 70%;
        @include ellipsis
      }
    }
    >ul{
      >li{
        padding: 4px 0 4px 0;
      }
    }
    i{
      width: 12px;
      height: 20px;
      display: inline-block;
      vertical-align: top;
      margin-top: 4px;
      font-size: 10px;
      color: $color-grid;
    }
    .label{
      &:hover{
        color: $color;
      }
    }
    .item-handle-area{
      height: 24px;
      position: relative;
    }
    .check{
      display: inline-block;
      position: relative;
      top: -1px;
    }
    .add-icon{
      position: absolute;
      top: 8px;
      right: 0;
    }
    .inputCheck{
      position: absolute;
      background: #fff;
      border: 1px $color-line solid;
      text-align: center;
      right: 0;
      top: 5px;
    }
    .notAllNodes{
      background: $color;
    }
    .inputHover{
      border: 1px $color-line solid;
      .icon-tick{
        color: $color;
        margin-top: 0;
      }
    }
  }
  .halo-tree li > span,
  .halo-tree li > i,
  .halo-tree li > a {
    line-height: 20px;
    vertical-align: middle;
  }

  /* loading */
  .halo-tree li span.halo-tree-iconEle {
    margin: 0;
    width: 24px;
    height: 24px;
    line-height: 20px;
    display: inline-block;
    vertical-align: top;
    border: 0 none;
    cursor: pointer;
    outline: none;
    text-align: center;
  }

  .halo-tree li span.halo-tree-icon_loading::after {
    display: inline-block;
    font-family: 'iconfont';
    text-rendering: optimizeLegibility;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    content: "\e6ae";
    -webkit-animation: loadingCircle 2s infinite linear;
    animation: loadingCircle 2s infinite linear;

  }

  @keyframes loadingCircle {
    0% {
      transform-origin: 50% 50%;
      transform: rotate(0deg);
    }
    100% {
      transform-origin: 50% 50%;
      transform: rotate(360deg);
    }
  }

  .halo-tree li:last-child::before {
    height: 26px
  }
  .defaultTreeColor{
    color: $color;
  }
  .dapart-arror{
    position: absolute;
    right: 20px;
    top: 3px;
    >p{
      font-size: $font-size-smallest;
    }
  }
  .dapart-arror-icon{
    position: absolute;
    right: 20px;
    top: 0;
    .icon-jiantou{
      font-size: $font-size-large;
    }
  }
  .depart-select{
    position: absolute;
    right: 0;
    top: -3px;
    color: $color;
  }
  .halo-tree-padding{
    >ul{
      > li{
        padding-left: 20px;
      }
    }
  }
</style>
